<?php
/**
 *
 * @author Lukas Normantas
 */
class Default_Model_User extends Doctrine_Record
{

    protected $_userForm = null;

    protected $_registerForm = null;

    protected $_loginForm = null;

    protected $_profileForm = null;

    protected $_emailForm = null;

    protected $_newEmailForm = null;

    protected $_lostPasswordForm = null;

    protected $_updatePasswordForm = null;

    protected $_passwordChangeForm = null;

    public function setTableDefinition()
    {
        $this->setTableName('users');
        $this->hasColumn('first_name', 'string', 50);
        $this->hasColumn('last_name', 'string', 50);
        $this->hasColumn('password', 'string', 50);
        $this->hasColumn('email', 'string', 255);
        $this->hasColumn('status', 'enum', null,
            array('values' => array('awaiting_registration_confirm', 'regular'))
        );
        $this->hasColumn('role', 'string', 50, array('default' => 'member'));
    }

    public function setUp()
    {
        $this->actAs('Timestampable');
        $this->hasMany('Default_Model_UserRegistrationConfirm as RegistrationConfirms', array(
                'local' => 'id',
                'foreign' => 'user_id'
            )
        );
        $this->hasMany('Default_Model_UserPasswordChange as PasswordChanges', array(
                'local' => 'id',
                'foreign' => 'user_id'
            )
        );
        $this->hasMany('Default_Model_UserEmailChange as EmailChanges', array(
                'local' => 'id',
                'foreign' => 'user_id'
            )
        );

    }

    public function getUserForm(){
        if ($this->_userForm == null){
            $this->_userForm = new Default_Form_UserForm();
            $this->_userForm->setDefaults($this->toArray());
        }
        return $this->_userForm;
    }

    public function getProfileForm($user_id = null){
        if ($this->_profileForm == null){
            $this->_profileForm = new Default_Form_EditProfile();
            $this->_profileForm->setDefaults($this->toArray());
        }
        return $this->_profileForm;
    }

    public function getRegisterForm(){
        if ($this->_registerForm == null){
            $this->_registerForm = new Default_Form_RegisterForm();
        }
        return $this->_registerForm ;
    }

    /**
     *
     * @return Default_Form_LoginForm
     */
    public function getLoginForm(){
        if ($this->_loginForm == null){
            $this->_loginForm = new Default_Form_LoginForm();
        }
        return $this->_loginForm ;
    }

    public function getEmailForm(){
        if ($this->_emailForm == null){
            $this->_emailForm = new Default_Form_Email();
        }
        return $this->_emailForm ;
    }

    public function getNewEmailForm(){
        if ($this->_newEmailForm == null){
            $this->_newEmailForm = new Default_Form_NewEmail();
        }
        return $this->_newEmailForm ;
    }

    public function getLostPasswordForm(){
        if ($this->_lostPasswordForm == null){
            $this->_lostPasswordForm = new Default_Form_LostPassword();
        }
        return $this->_lostPasswordForm ;
    }

    public function getUpdatePasswordForm(){
        if ($this->_updatePasswordForm == null){
            $this->_updatePasswordForm = new Default_Form_UpdatePassword();
        }
        return $this->_updatePasswordForm ;
    }


    /**
     *
     * @return Default_Form_PasswordChange
     */
    public function getPasswordChangeForm(){
        if ($this->_passwordChangeForm == null){
            $this->_passwordChangeForm = new Default_Form_PasswordChange();
        }
        return $this->_passwordChangeForm ;
    }


    public function edit($data)
    {
        $form = $this->getUserForm();
        if ($form->isValid( $data )){
            $values = $form->getValues();
            if ( ! $values['id']) unset($values['id']);
            $this->fromArray($values);
            $this->save();
            return true;
        }
        return false;
    }

    public function editProfile($data, $user_id)
    {
        $form = $this->getProfileForm();
        if ($form->isValid( $data )){
            $this->fromArray($form->getValues());
            $this->save();
            return true;
        }
        return false;
    }

    public function register($data, Zend_View $view)
    {
        $form = $this->getRegisterForm();
        if ($form->isValid( $data )){
            $this->fromArray($form->getValues());
            $this->status='awaiting_registration_confirm';
            $confirm = new Default_Model_UserRegistrationConfirm();
            $confirm->code = md5(microtime());
            $this->RegistrationConfirms->delete();
            $this->RegistrationConfirms[] = $confirm;
            $this->save();
            $this->refresh(true);

            $identity = new Areal_Auth_Identity();
            $identity->setEmail($data['email']);
            $identity->setPassword($data['password']);
            $auth = Zend_Auth::getInstance();
            $auth->authenticate($identity);

            $view->user = $this;
            $mail = new Zend_Mail();
            $mail->setBodyText($view->render('email-register.phtml'));
            $mail->setFrom(APPLICATION_EMAIL, '');
            $mail->addTo($this['email'], $this['first_name'] . ' ' . $this['first_name']);
            $mail->setSubject('Registration');
            $mail->send();
            return true ;
        }
        return false;
    }

    public function login($post)
    {
        $loginForm = $this->getLoginForm();
        $identity = new Areal_Auth_Identity();
        $loginForm->isValid($post);

        $identity->setEmail($loginForm->getValue('login_email'));
        $identity->setPassword($loginForm->getValue('login_password'));
        $auth = Zend_Auth::getInstance();
        $result = $auth->authenticate($identity);
        if ( $result->getCode() !== Zend_Auth_Result::SUCCESS ) {
            return false;
        } else {
            return true;
        }
    }

    static public function confirmRegistration($user_id, $registration_code)
    {
        $user = Doctrine_Query::create()
            ->from('Default_Model_User u')
            ->innerJoin('u.RegistrationConfirms c')
            ->where('u.id = ?', $user_id)
            ->andWhere('c.code = ?', $registration_code)
            ->fetchOne(null, Doctrine::HYDRATE_RECORD);
        if ($user){
            $user->status = 'regular';
            $user->save();
            $user->RegistrationConfirms->delete();
            return true;
        }
        return false;
    }

    public function grantPasswordChange($data, Zend_View $view)
    {
        $form = $this->getEmailForm();
        if ($form->isValid( $data )){
            $user = Doctrine_Query::create()
                ->from('Default_Model_User u')
                ->leftJoin('u.PasswordChanges c')
                ->where('u.email = ?', $data['email'])
                ->fetchOne(null, Doctrine::HYDRATE_RECORD);
            if ( ! $user) return false;
            $user->PasswordChanges->delete();
            $user->PasswordChanges[]['code'] = md5(microtime());
            $user->save();

            // sends email with link to change-lost-password action
            $view->user = $user;
            $mail = new Zend_Mail();
            $mail->setBodyText($view->render('email-link-to-password-change.phtml'));
            $mail->setFrom(APPLICATION_EMAIL, '');
            $mail->addTo($user['email'], $user['first_name'] . ' ' . $user['last_name']);
            $mail->setSubject('Password change');
            $mail->send();
            return true;
        }
        return false;
    }

    static public function isPasswordChangeGranted($user_id, $code){
        $user = Doctrine_Query::create()
            ->from('Default_Model_User u')
            ->innerJoin('u.PasswordChanges c')
            ->where('u.id = ?', $user_id)
            ->andWhere('c.code = ?', $code)
            ->fetchOne(null, Doctrine::HYDRATE_RECORD);
        if ($user) return $user;
        return false;
    }

    public function editLostPassword($data)
    {
        $form = $this->getLostPasswordForm();
        if ($form->isValid( $data )){
            $this->fromArray($form->getValues());
            $this->PasswordChanges->delete();
            $this->save();
            return true;
        }
        return false;
    }

    public function changePassword($data)
    {
        $form = $this->getPasswordChangeForm();
        if ($form->isValid( $data )){
            $this->fromArray($form->getValues());
            $this->save();
            return true;
        }
        return false;
    }

    public function grantEmailChange($data, Zend_View $view)
    {
        $form = $this->getNewEmailForm();
        if ($form->isValid( $data )){
            $this->EmailChanges->delete();
            $change = new Default_Model_UserEmailChange();
            $change->code = md5(microtime());
            $change->new_email = $data['email'];
            $this->EmailChanges[] = $change;
            $this->save();
            // sends email with link to confirm-new-email action
            $view->user = $this;
            $mail = new Zend_Mail();
            $mail->setBodyText($view->render('email-link-to-email-change.phtml'));
            $mail->setFrom(APPLICATION_EMAIL, '');
            $mail->addTo($data['email'], $this['first_name'] . ' ' . $this['last_name']);
            $mail->setSubject('Email change');
            $mail->send();
            return true;
        }
        return false;
    }

    static public function confirmNewEmail($user_id, $code)
    {
        $user = Doctrine_Query::create()
            ->from('Default_Model_User u')
            ->innerJoin('u.EmailChanges c')
            ->where('u.id = ?', $user_id)
            ->andWhere('c.code = ?', $code)
            ->fetchOne(null, Doctrine::HYDRATE_RECORD);
        if ($user){
            $user->email = $user->EmailChanges[0]->new_email;
            $userThatAlreadyExistsWithSuchEmail = Doctrine_Query::create()
                ->from('Default_Model_User u')
                ->where('u.email = ?', $user->EmailChanges[0]->new_email)
                ->fetchOne(null, Doctrine::HYDRATE_RECORD);
            $user->EmailChanges->delete();
            if ( $userThatAlreadyExistsWithSuchEmail ) {
                return false;
            } //else { continue; }
            $user->save();
            return true;
        }
        return false;
    }

    public function updatePassword($data)
    {
        $form = $this->getUpdatePasswordForm();
        if ($form->isValid( $data )){
            $this->fromArray($form->getValues());
            $this->save();
            return true;
        }
        return false;
    }
}
